/**
 * Set工具类，封装了一些使用Set数据结构的常用操作
 */
export class SetWrapper<T> {
  private __set: Set<T>;

  /**
   * 构造函数
   * @param {readonly T[] | undefined} values 可选的初始元素数组
   * @example
   * // 创建一个空的SetWrapper
   * const emptySet = new SetWrapper<number>();
   * 
   * // 创建带有初始数据的SetWrapper
   * const setWithData = new SetWrapper<number>([1, 2, 3]);
   */
  constructor(values?: readonly T[]) {
    this.__set = new Set(values);
  }

  /**
   * 获取内部Set实例
   * @returns {Set<T>} 内部的Set实例
   * @example
   * const set = new SetWrapper<number>([1, 2, 3]);
   * const internalSet = set.getSet(); // 返回原生Set对象
   */
  getSet(): Set<T> {
    return this.__set;
  }

  /**
   * 添加元素
   * @param {T} value 要添加的元素
   * @returns {this} 返回SetWrapper实例，支持链式调用
   * @example
   * const set = new SetWrapper<number>();
   * set.add(1).add(2).add(3); // 链式调用
   */
  add(value: T): this {
    this.__set.add(value);
    return this;
  }

  /**
   * 添加多个元素
   * @param {T[]} values 要添加的元素数组
   * @returns {this} 返回SetWrapper实例，支持链式调用
   * @example
   * const set = new SetWrapper<number>();
   * set.addMultiple([1, 2, 3]);
   */
  addMultiple(values: T[]): this {
    values.forEach(value => this.__set.add(value));
    return this;
  }

  /**
   * 检查是否包含指定元素
   * @param {T} value 要检查的元素
   * @returns {boolean} 是否包含指定元素
   * @example
   * const set = new SetWrapper<number>([1, 2, 3]);
   * console.log(set.has(1)); // true
   * console.log(set.has(4)); // false
   */
  has(value: T): boolean {
    return this.__set.has(value);
  }

  /**
   * 删除指定元素
   * @param {T} value 要删除的元素
   * @returns {boolean} 是否成功删除（元素是否存在）
   * @example
   * const set = new SetWrapper<number>([1, 2, 3]);
   * console.log(set.delete(1)); // true
   * console.log(set.delete(4)); // false
   */
  delete(value: T): boolean {
    return this.__set.delete(value);
  }

  /**
   * 删除多个元素
   * @param {T[]} values 要删除的元素数组
   * @example
   * const set = new SetWrapper<number>([1, 2, 3, 4]);
   * set.deleteMultiple([1, 3]); // 删除元素1和3
   */
  deleteMultiple(values: T[]): void {
    values.forEach(value => this.__set.delete(value));
  }

  /**
   * 清空Set
   * @example
   * const set = new SetWrapper<number>([1, 2, 3]);
   * set.clear(); // Set变为空
   */
  clear(): void {
    this.__set.clear();
  }

  /**
   * 获取Set的大小
   * @returns {number} Set中元素的数量
   * @example
   * const set = new SetWrapper<number>([1, 2, 3]);
   * console.log(set.size()); // 3
   */
  size(): number {
    return this.__set.size;
  }

  /**
   * 检查Set是否为空
   * @returns {boolean} Set是否为空
   * @example
   * const emptySet = new SetWrapper<number>();
   * console.log(emptySet.isEmpty()); // true
   * 
   * const setWithData = new SetWrapper<number>([1, 2, 3]);
   * console.log(setWithData.isEmpty()); // false
   */
  isEmpty(): boolean {
    return this.__set.size === 0;
  }

  /**
   * 获取所有元素的数组
   * @returns {T[]} 包含所有元素的数组
   * @example
   * const set = new SetWrapper<number>([1, 2, 3]);
   * console.log(set.toArray()); // [1, 2, 3]
   */
  toArray(): T[] {
    return Array.from(this.__set);
  }

  /**
   * 对Set中的每个元素执行回调函数
   * @param {(value: T, value2: T, set: Set<T>) => void} callback 回调函数
   * @example
   * const set = new SetWrapper<number>([1, 2, 3]);
   * set.forEach(value => {
   *   console.log(value);
   * });
   * // 输出: 
   * // 1
   * // 2
   * // 3
   */
  forEach(callback: (value: T, value2: T, set: Set<T>) => void): void {
    this.__set.forEach(callback);
  }

  /**
   * 根据回调函数过滤Set
   * @param {(value: T) => boolean} predicate 过滤条件回调函数
   * @returns {SetWrapper<T>} 过滤后的新SetWrapper实例
   * @example
   * const set = new SetWrapper<number>([1, 2, 3, 4]);
   * const filtered = set.filter(value => value > 2);
   * console.log(filtered.toArray()); // [3, 4]
   */
  filter(predicate: (value: T) => boolean): SetWrapper<T> {
    const filteredSet = new SetWrapper<T>();
    this.forEach((value) => {
      if (predicate(value)) {
        filteredSet.add(value);
      }
    });
    return filteredSet;
  }

  /**
   * 对Set中的每个元素执行映射函数
   * @template U
   * @param {(value: T) => U} mapper 映射函数
   * @returns {SetWrapper<U>} 映射后的新SetWrapper实例
   * @example
   * const set = new SetWrapper<number>([1, 2, 3]);
   * const squaredSet = set.map(value => value * value);
   * console.log(squaredSet.toArray()); // [1, 4, 9]
   */
  map<U>(mapper: (value: T) => U): SetWrapper<U> {
    const mappedSet = new SetWrapper<U>();
    this.forEach((value) => {
      mappedSet.add(mapper(value));
    });
    return mappedSet;
  }

  /**
   * 对Set中的所有元素执行归约操作
   * @template U
   * @param {(accumulator: U, value: T) => U} reducer 归约函数
   * @param {U} initialValue 初始值
   * @returns {U} 归约结果
   * @example
   * const set = new SetWrapper<number>([1, 2, 3]);
   * const sum = set.reduce((acc, value) => acc + value, 0);
   * console.log(sum); // 6
   */
  reduce<U>(reducer: (accumulator: U, value: T) => U, initialValue: U): U {
    let accumulator = initialValue;
    this.forEach((value) => {
      accumulator = reducer(accumulator, value);
    });
    return accumulator;
  }

  /**
   * 检查Set中的所有元素是否满足条件
   * @param {(value: T) => boolean} predicate 条件函数
   * @returns {boolean} 是否所有元素都满足条件
   * @example
   * const set = new SetWrapper<number>([1, 2, 3]);
   * console.log(set.every(value => value > 0)); // true
   * console.log(set.every(value => value > 1)); // false
   */
  every(predicate: (value: T) => boolean): boolean {
    for (const value of this.__set) {
      if (!predicate(value)) {
        return false;
      }
    }
    return true;
  }

  /**
   * 检查Set中是否至少有一个元素满足条件
   * @param {(value: T) => boolean} predicate 条件函数
   * @returns {boolean} 是否至少有一个元素满足条件
   * @example
   * const set = new SetWrapper<number>([1, 2, 3]);
   * console.log(set.some(value => value > 2)); // true
   * console.log(set.some(value => value > 3)); // false
   */
  some(predicate: (value: T) => boolean): boolean {
    for (const value of this.__set) {
      if (predicate(value)) {
        return true;
      }
    }
    return false;
  }

  /**
   * 查找第一个满足条件的元素
   * @param {(value: T) => boolean} predicate 条件函数
   * @returns {T | undefined} 找到的元素或undefined
   * @example
   * const set = new SetWrapper<number>([1, 2, 3]);
   * const found = set.find(value => value > 1);
   * console.log(found); // 2
   */
  find(predicate: (value: T) => boolean): T | undefined {
    for (const value of this.__set) {
      if (predicate(value)) {
        return value;
      }
    }
    return undefined;
  }

  /**
   * 合并两个Set（并集）
   * @param {Set<T> | SetWrapper<T>} otherSet 另一个Set或SetWrapper实例
   * @returns {SetWrapper<T>} 合并后的新SetWrapper实例
   * @example
   * const set1 = new SetWrapper<number>([1, 2, 3]);
   * const set2 = new SetWrapper<number>([3, 4, 5]);
   * const union = set1.union(set2);
   * console.log(union.toArray()); // [1, 2, 3, 4, 5]
   */
  union(otherSet: Set<T> | SetWrapper<T>): SetWrapper<T> {
    const result = new SetWrapper<T>(this.toArray());
    const otherValues = otherSet instanceof SetWrapper ? otherSet.toArray() : Array.from(otherSet);
    result.addMultiple(otherValues);
    return result;
  }

  /**
   * 获取两个Set的交集
   * @param {Set<T> | SetWrapper<T>} otherSet 另一个Set或SetWrapper实例
   * @returns {SetWrapper<T>} 交集后的新SetWrapper实例
   * @example
   * const set1 = new SetWrapper<number>([1, 2, 3, 4]);
   * const set2 = new SetWrapper<number>([3, 4, 5]);
   * const intersection = set1.intersection(set2);
   * console.log(intersection.toArray()); // [3, 4]
   */
  intersection(otherSet: Set<T> | SetWrapper<T>): SetWrapper<T> {
    const result = new SetWrapper<T>();
    const otherSetInstance = otherSet instanceof SetWrapper ? otherSet.getSet() : otherSet;

    this.forEach((value) => {
      if (otherSetInstance.has(value)) {
        result.add(value);
      }
    });

    return result;
  }

  /**
   * 获取两个Set的差集（当前Set中有而另一个Set中没有的元素）
   * @param {Set<T> | SetWrapper<T>} otherSet 另一个Set或SetWrapper实例
   * @returns {SetWrapper<T>} 差集后的新SetWrapper实例
   * @example
   * const set1 = new SetWrapper<number>([1, 2, 3, 4]);
   * const set2 = new SetWrapper<number>([3, 4, 5]);
   * const difference = set1.difference(set2);
   * console.log(difference.toArray()); // [1, 2]
   */
  difference(otherSet: Set<T> | SetWrapper<T>): SetWrapper<T> {
    const result = new SetWrapper<T>();
    const otherSetInstance = otherSet instanceof SetWrapper ? otherSet.getSet() : otherSet;

    this.forEach((value) => {
      if (!otherSetInstance.has(value)) {
        result.add(value);
      }
    });

    return result;
  }

  /**
   * 获取两个Set的对称差集（只在其中一个Set中出现的元素）
   * @param {Set<T> | SetWrapper<T>} otherSet 另一个Set或SetWrapper实例
   * @returns {SetWrapper<T>} 对称差集后的新SetWrapper实例
   * @example
   * const set1 = new SetWrapper<number>([1, 2, 3, 4]);
   * const set2 = new SetWrapper<number>([3, 4, 5]);
   * const symmetricDiff = set1.symmetricDifference(set2);
   * console.log(symmetricDiff.toArray()); // [1, 2, 5]
   */
  symmetricDifference(otherSet: Set<T> | SetWrapper<T>): SetWrapper<T> {
    const result = new SetWrapper<T>();
    const otherSetInstance = otherSet instanceof SetWrapper ? otherSet.getSet() : otherSet;

    // 添加当前Set中有而另一个Set中没有的元素
    this.forEach((value) => {
      if (!otherSetInstance.has(value)) {
        result.add(value);
      }
    });

    // 添加另一个Set中有而当前Set中没有的元素
    otherSetInstance.forEach((value) => {
      if (!this.__set.has(value)) {
        result.add(value);
      }
    });

    return result;
  }

  /**
   * 检查当前Set是否是另一个Set的子集
   * @param {Set<T> | SetWrapper<T>} otherSet 另一个Set或SetWrapper实例
   * @returns {boolean} 当前Set是否是另一个Set的子集
   * @example
   * const set1 = new SetWrapper<number>([1, 2]);
   * const set2 = new SetWrapper<number>([1, 2, 3]);
   * console.log(set1.isSubsetOf(set2)); // true
   * console.log(set2.isSubsetOf(set1)); // false
   */
  isSubsetOf(otherSet: Set<T> | SetWrapper<T>): boolean {
    if (this.size() > (otherSet instanceof SetWrapper ? otherSet.size() : otherSet.size)) {
      return false;
    }

    const otherSetInstance = otherSet instanceof SetWrapper ? otherSet.getSet() : otherSet;

    return this.every((value) => otherSetInstance.has(value));
  }

  /**
   * 创建SetWrapper的浅拷贝
   * @returns {SetWrapper<T>} 新的SetWrapper实例
   * @example
   * const original = new SetWrapper<number>([1, 2, 3]);
   * const clone = original.clone();
   * console.log(clone.toArray()); // [1, 2, 3]
   * console.log(original !== clone); // true
   */
  clone(): SetWrapper<T> {
    return new SetWrapper<T>(this.toArray());
  }

  /**
   * 对Set中的元素进行排序
   * @param {(a: T, b: T) => number} [comparator] 比较函数
   * @returns {SetWrapper<T>} 排序后的新SetWrapper实例
   * @example
   * const set = new SetWrapper<string>(['c', 'a', 'b']);
   * const sorted = set.sort();
   * console.log(sorted.toArray()); // ['a', 'b', 'c']
   * 
   * // 使用自定义比较函数
   * const reverseSorted = set.sort((a, b) => b.localeCompare(a));
   * console.log(reverseSorted.toArray()); // ['c', 'b', 'a']
   */
  sort(comparator?: (a: T, b: T) => number): SetWrapper<T> {
    const sortedArray = this.toArray().sort(comparator);
    return new SetWrapper<T>(sortedArray);
  }

  /**
   * 获取Set中的最大值
   * @param {(value: T) => number} [extractor] 可选的值提取函数
   * @returns {T | undefined} 值最大的元素或undefined（如果Set为空）
   * @example
   * const set = new SetWrapper<number>([10, 30, 20]);
   * console.log(set.max()); // 30
   * 
   * // 使用提取函数
   * const objSet = new SetWrapper<{ value: number }>([
   *   { value: 10 },
   *   { value: 30 },
   *   { value: 20 }
   * ]);
   * console.log(set.max(item => item.value)); // { value: 30 }
   */
  max(extractor?: (value: T) => number): T | undefined {
    if (this.isEmpty()) return undefined;

    let max: T | undefined;
    let maxExtracted: number | undefined;

    this.forEach((value) => {
      const extracted = extractor ? extractor(value) : (value as unknown as number);
      if (maxExtracted === undefined || extracted > maxExtracted) {
        max = value;
        maxExtracted = extracted;
      }
    });

    return max;
  }

  /**
   * 获取Set中的最小值
   * @param {(value: T) => number} [extractor] 可选的值提取函数
   * @returns {T | undefined} 值最小的元素或undefined（如果Set为空）
   * @example
   * const set = new SetWrapper<number>([10, 30, 20]);
   * console.log(set.min()); // 10
   * 
   * // 使用提取函数
   * const objSet = new SetWrapper<{ value: number }>([
   *   { value: 10 },
   *   { value: 30 },
   *   { value: 20 }
   * ]);
   * console.log(set.min(item => item.value)); // { value: 10 }
   */
  min(extractor?: (value: T) => number): T | undefined {
    if (this.isEmpty()) return undefined;

    let min: T | undefined;
    let minExtracted: number | undefined;

    this.forEach((value) => {
      const extracted = extractor ? extractor(value) : (value as unknown as number);
      if (minExtracted === undefined || extracted < minExtracted) {
        min = value;
        minExtracted = extracted;
      }
    });

    return min;
  }

  /**
   * 从数组创建SetWrapper实例
   * @template T
   * @param {T[]} array 源数组
   * @returns {SetWrapper<T>} 新的SetWrapper实例
   * @example
   * const array = [1, 2, 3, 2, 1];
   * const set = SetWrapper.fromArray(array);
   * console.log(set.toArray()); // [1, 2, 3] (自动去重)
   */
  static fromArray<T>(array: T[]): SetWrapper<T> {
    return new SetWrapper<T>(array);
  }
}